feat: route pkg@version from deps, direct nav, and search for any valid specifier#1723
feat: route pkg@version from deps, direct nav, and search for any valid specifier#1723
pkg@version from deps, direct nav, and search for any valid specifier#1723Conversation
…nstead of 404 Dependency links with version ranges (e.g. "^18.0.0 || ^19.0.0", ">15 <=16.0.2") previously navigated to a non-existent version page and 404'd. Now `packageRoute()` distinguishes exact versions from ranges: exact versions link to the version page, while ranges link to the package page with `?semver=<range>#versions`, pre-populating the existing "Filter by semver" input. Closes #1120
Searching for `esbuild@0.25.12` or `@angular/core@^18` and pressing Enter now navigates directly to the package version page (or semver filter for ranges) instead of returning no results. Since in the previous commit I added support for linking to the package page with the a pre-filled semver version specifier in the query string to populate the version filter, this supports both exact versions and semver ranges in the search input. Closes #1416
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
pkg@version from deps, direct nav, and search for any valid specifierpkg@version from deps, direct nav, and search for any valid specifier
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
Awesome idea, I really like this one. Two birds with one stone 🚀 |
📝 WalkthroughWalkthroughThis PR adds support for navigating directly to specific package versions from the search interface using "pkg@version" notation. It introduces a new Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 1✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (3)
shared/utils/parse-package-param.ts (1)
54-61: Trailing@edge case may produce unexpected results.When the input ends with
@but has no version (e.g.,'esbuild@'), the function returns{ name: 'esbuild@' }because theversionslice is empty. This retains the trailing@in the package name, which is not a valid npm package name.Consider whether this should instead return
{ name: 'esbuild' }to strip the trailing@:💡 Suggested fix
export function parsePackageSpecifier(input: string): { name: string; version?: string } { const atIndex = input.startsWith('@') ? input.indexOf('@', 1) : input.indexOf('@') if (atIndex > 0) { const version = input.slice(atIndex + 1) if (version) return { name: input.slice(0, atIndex), version } + // Trailing @ with no version - return name without the @ + return { name: input.slice(0, atIndex) } } return { name: input } }modules/runtime/server/cache.ts (1)
222-238: Consider usingparsePackageSpecifierto reduce code duplication.This function contains inline parsing logic for extracting the package name and version specifier (lines 226-238) that duplicates the logic in
parsePackageSpecifier. The same pattern appears inprocessSingleVersionsMeta(lines 300-312).Since
parsePackageSpecifierwas introduced to centralise this parsing, consider refactoring these functions to use it for consistency and maintainability.♻️ Suggested refactor
async function processSingleFastNpmMeta( packageQuery: string, storage: ReturnType<typeof useStorage>, metadata: boolean, ): Promise<Record<string, unknown>> { - let packageName = packageQuery - let specifier = 'latest' - - if (packageName.startsWith('@')) { - const atIndex = packageName.indexOf('@', 1) - if (atIndex !== -1) { - specifier = packageName.slice(atIndex + 1) - packageName = packageName.slice(0, atIndex) - } - } else { - const atIndex = packageName.indexOf('@') - if (atIndex !== -1) { - specifier = packageName.slice(atIndex + 1) - packageName = packageName.slice(0, atIndex) - } - } + const { name: packageName, version } = parsePackageSpecifier(packageQuery) + const specifier = version ?? 'latest'test/unit/app/utils/router.spec.ts (1)
100-107: Consider adding a test case forundefinedversion.The test covers
nullversion but notundefined. Since the function signature acceptsstring | null | undefined, it would be good to explicitly test theundefinedcase for completeness.💡 Suggested addition
describe('with null/undefined version', () => { it('returns package route for null version', () => { expect(packageRoute('react', null)).toEqual({ name: 'package', params: { org: '', name: 'react' }, }) }) + + it('returns package route for undefined version', () => { + expect(packageRoute('react', undefined)).toEqual({ + name: 'package', + params: { org: '', name: 'react' }, + }) + }) })
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
app/components/Package/Versions.vueapp/pages/search.vueapp/utils/router.tsmodules/runtime/server/cache.tsshared/utils/parse-package-param.tstest/e2e/search-at-version.spec.tstest/unit/app/utils/router.spec.tstest/unit/shared/utils/parse-package-param.spec.ts
🔗 Linked issue
Closes #1120
Closes #1416
🧭 Context
We have two seemingly separate issues:
^18.0.0 || ^19.0.0,>15 <=16.0.2) currently navigate to a non-existent version page and result in a 404.nuxt@4.0.1ornuxt@>=4ornuxt@>=4<6(convenient if pasting from somewhere) does not result in a match. There's a proposed temporary solution in feat: strip version info from the search query #1626 to strip the version segment from the query.📚 Description
https://npmx.dev/package/nuxt/v/:versionwill route to the specific versioned package page ifversionis a specific version string and route to the package page with?semver=<version>otherwise.nuxt@4.0.1ornuxt@>=4ornuxt@>=4<6and pressing Enter now navigates directly to the package version page for a specific version or to the semver-filtered package page for a semver specifier, instead of returning no results. This just works for both exact versions and semver ranges, because of the above routing change.npmx.smart.pkg@v.routing.mp4